package frontend.pages.worklog.closemonth;

import backend.model.other.MonthState;
import backend.service.other.MonthStateService;
import frontend.components.form.ValidatableForm;
import frontend.core.TimeTrackingWebApplication;
import frontend.model.worklog.MonthStateUIModel;
import shared.util.CalendarUtils;
import frontend.components.base.ComponentFactory;
import frontend.components.other.UserInputCallableAction;
import org.apache.log4j.Logger;
import org.apache.wicket.Localizer;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.IChoiceRenderer;
import org.apache.wicket.markup.html.panel.Panel;
import shared.other.MonthStateEnum;

import java.util.Arrays;
import java.util.Calendar;
import java.util.List;

public class MonthStateForm extends ValidatableForm<MonthStateUIModel> {
    private static Logger logger = Logger.getLogger(MonthStateForm.class);

    private static final String MONTH_LABEL = "pages.monthStatePage.form.chooseMonth";
    private static final String CURRENT_STATUS_LABEL = "pages.monthStatePage.form.currentStatus";
    private static final String NEW_STATUS_LABEL = "pages.monthStatePage.form.newStatus";
    public static final String RESOURCE_KEY_INFO_ENTITY_SAVED_SUCCESSFULLY = "info.entity.saved.successfully";

    private Panel currentStatusComponent;

    public MonthStateForm(String id, MonthStateUIModel monthModel) {
        super(id, monthModel);
    }

    @Override
    protected void constructFormContent() {
        Panel monthYearChoiceComponent = ComponentFactory.createDoubleDropDownChoiceComponent("monthYearComponent", MONTH_LABEL, "month", "year", uiModel,
                getAvailableMonths(), getAvailableYears(), getMonthRenderer(), getYearRenderer(), false, getOnSelectAction(), getOnSelectAction());
        currentStatusComponent = ComponentFactory.createTextFieldComponent("currentStatusDisplayValue", CURRENT_STATUS_LABEL, uiModel);
        currentStatusComponent.setEnabled(false);
        Panel newStatusComponent = ComponentFactory.createDropDownChoiceComponent("newStatus", NEW_STATUS_LABEL, uiModel,
                Arrays.asList(MonthStateEnum.values()), getMonthStateRenderer(), false);
        AjaxButton saveButton = createSaveButton();

        add(monthYearChoiceComponent, currentStatusComponent, newStatusComponent, saveButton);
    }

    private AjaxButton createSaveButton() {
        AjaxButton showWorkLogButton = new AjaxButton("saveButton", this) {
            @Override
            protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
                uiModel.populateDBModelFromFields();
                MonthState monthState = uiModel.getDBModel();
                MonthStateService service = TimeTrackingWebApplication.getService(MonthStateService.class);
                service.saveOrUpdateDBModel(monthState);
                uiModel.populateFieldsFromDBModel();
                info(CalendarUtils.appendCurrentTime(Localizer.get().getString(RESOURCE_KEY_INFO_ENTITY_SAVED_SUCCESSFULLY, null)));
                target.add(currentStatusComponent);
                target.add(feedbackPanel);
            }

            @Override
            protected void onError(AjaxRequestTarget target, Form<?> form) {
                logger.error("Error occurred while submitting form.");
            }
        };
        return showWorkLogButton;
    }

    private List<Integer> getAvailableMonths() {
        List<Integer> availableMonths = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
        return availableMonths;
    }

    private List<Integer> getAvailableYears() {
        int currentYear = Calendar.getInstance().get(Calendar.YEAR);
        List<Integer> availableYears = Arrays.asList(currentYear - 1, currentYear);
        return availableYears;
    }

    public IChoiceRenderer<Integer> getMonthRenderer() {
        return new IChoiceRenderer<Integer>() {
            @Override
            public Object getDisplayValue(Integer monthOneBased) {
                String monthResourceKey = CalendarUtils.getMonthResourceKey(monthOneBased - 1);
                return Localizer.get().getString(monthResourceKey, null);
            }

            @Override
            public String getIdValue(Integer object, int index) {
                return String.valueOf(object);
            }
        };
    }

    public IChoiceRenderer<Integer> getYearRenderer() {
        return new IChoiceRenderer<Integer>() {
            @Override
            public Object getDisplayValue(Integer year) {
                return String.valueOf(year);
            }

            @Override
            public String getIdValue(Integer object, int index) {
                return String.valueOf(object);
            }
        };
    }

    IChoiceRenderer<MonthStateEnum> getMonthStateRenderer() {
        return new IChoiceRenderer<MonthStateEnum>() {
            @Override
            public Object getDisplayValue(MonthStateEnum object) {
                return object.getDisplayValue();
            }

            @Override
            public String getIdValue(MonthStateEnum object, int index) {
                return object.toString();
            }
        };
    }

    public UserInputCallableAction<Integer> getOnSelectAction() {
        return new UserInputCallableAction<Integer>() {
            @Override
            public void call(AjaxRequestTarget target, Integer userInput) {
                int selectedYear = uiModel.getYear();
                int selectedMonth = uiModel.getMonth();
                MonthState dbMonthState = getDbMonthState(selectedMonth, selectedYear);
                if (dbMonthState != null) {
                    uiModel.setMonthState(dbMonthState);
                } else {
                    uiModel.setCurrentStatus(MonthStateEnum.OPENED);
                }
                target.add(feedbackPanel);
                target.add(currentStatusComponent);
            }
        };
    }

    private MonthState getDbMonthState(int month, int year) {
        MonthStateService service = TimeTrackingWebApplication.getService(MonthStateService.class);
        MonthState dbMonthState = service.findMonthStateByMonthAndYear(month, year);
        return dbMonthState;
    }

    @Override
    protected void doFormValidation() {
        // No validation needed
    }
}
